package yz.cp.back.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import yz.cp.back.common.base.BaseController;
import yz.cp.back.common.enums.BillType;
import yz.cp.back.common.enums.MerchantType;
import yz.cp.back.common.enums.RoleType;
import yz.cp.back.common.res.ApiResult;
import yz.cp.back.common.utils.PageKit;
import yz.cp.back.f.entity.FinanceDeal;
import yz.cp.back.f.service.IFinanceDealService;
import yz.cp.back.u.entity.UserAccount;
import yz.cp.back.u.entity.UserBank;
import yz.cp.back.u.entity.UserRating;
import yz.cp.back.u.entity.UserRole;
import yz.cp.back.u.service.IUserAccountService;
import yz.cp.back.u.service.IUserBankService;
import yz.cp.back.u.service.IUserRatingService;
import yz.cp.back.u.service.IUserRoleService;
import yz.cp.back.user.service.UserRoleMange;
import yz.cp.back.user.vo.AccountBillVo;
import yz.cp.back.user.vo.UserAccountQueryVo;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/web/userAccount")
public class UserAccountController extends BaseController {
    @Autowired
    private UserRoleMange userRoleMange;
    @Autowired
    private IUserBankService userBankService;
    @Autowired
    private IUserAccountService userAccountService;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IFinanceDealService financeDealService;
    @Autowired
    private IUserRatingService userRatingService;
    public UserRole userRoleConstant = new UserRole();

    @PostMapping("getByCondition")
    public ApiResult getByCondition(UserAccountQueryVo vo) {
        Map map = beanMapper.map(vo, Map.class);
        IPage<UserAccount> page = userAccountService.findByCondition(PageKit.buildPage(vo), map);
        if (page.getRecords() != null && page.getRecords().size() > 0) {
            List<String> roleList = Lists.newArrayList();
            page.getRecords().forEach(v ->
                    roleList.add(v.getId())
            );
            List<UserRole> userRoleList = userRoleMange.getAccessUserRoleById(roleList);
            page.convert(v -> {
                Map m = beanMapper.map(v, Map.class);
                Map m1 = Maps.newHashMap();
                BigDecimal allMoney = BigDecimal.ZERO;
                for (UserRole userRole : userRoleList) {
                    if (StringUtils.equals(userRole.getId(), v.getId())) {
                        m1.put("merchantName", userRole.getMerchantName());
                        m1.put("roleTypeName", RoleType.getByCode(userRole.getRoleType()).getName());
                        m1.put("roleType", userRole.getRoleType());
                        m1.put("accessId", userRole.getAccessId());
                        m1.put("accessName", userRole.getAccessName());
                        m1.put("merchantNo", userRole.getMerchantNo());
                        switch (userRole.getRoleType()) {
                            case 1:
                                //资金方
                                allMoney = allMoney.add(v.getMoneyAmount()).add(v.getDepositAmount()).add(v.getDueAmount());
                                break;
                            default:
                                allMoney = allMoney.add(v.getMoneyAmount()).add(v.getDepositAmount());
                        }
                    }
                }
                m.put("allMoney", allMoney);
                m.put("role", m1);
                return m;
            });
        }
        return renderOk().add(page);
    }

    @RequestMapping(value = "/disable/{id}", method = RequestMethod.POST)
    public ApiResult disable(@PathVariable String id) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(id);
        userAccount.setStatus(2);
        userAccountService.updateById(userAccount);
        return renderOk("操作成功");
    }

    @RequestMapping(value = "/enable/{id}", method = RequestMethod.POST)
    public ApiResult enable(@PathVariable String id) {
        UserAccount userAccount = new UserAccount();
        userAccount.setId(id);
        userAccount.setStatus(1);
        userAccountService.updateById(userAccount);
        return renderOk("操作成功");
    }

    @RequestMapping(value = "/detail/{id}", method = RequestMethod.POST)
    public ApiResult detail(@PathVariable String id) {
        UserAccount userAccount = userAccountService.getById(id);
        UserRole userRole = userRoleService.getById(id);
        UserBank userBank = userBankService.getById(id);
        if (userAccount == null || userRole == null) {
            return renderError("数据有误");
        }
        userRole.initNme();
        userAccount.initName();
        if (StringUtils.isNotBlank(userRole.getAccessId())) {
            UserRole access = userRoleService.getById(userRole.getAccessId());
            userRole.setAccessName(access.getMerchantName());
        } else {
            userRole.setAccessName("N/A");
        }
        if (userBank == null) {
            userBank = new UserBank();
        }
        Map extraMap = Maps.newHashMap();
        BigDecimal allMoney = BigDecimal.ZERO;
        Map<String, Object> money = Maps.newLinkedHashMap();
        Map<String, Object> deposit = Maps.newHashMap();
        Map<String, Object> others = Maps.newHashMap();

        List<JSONObject> moneyList = Lists.newLinkedList();
        List<JSONObject> depositList = Lists.newLinkedList();
        List<JSONObject> othersList = Lists.newLinkedList();
        money.put("list", moneyList);
        others.put("list", othersList);
        deposit.put("list", depositList);
        moneyList.add(build("资金余额:", userAccount.getMoneyAmount()));
        moneyList.add(build("可用资金:", userAccount.getMoneyUsable()));
        moneyList.add(build("在途资金:", userAccount.getMoneyInTransit()));
        moneyList.add(build("冻结资金:", userAccount.getMoneyFrozen()));
        List<JSONObject> moneyAdd = Lists.newLinkedList();
        List<JSONObject> moneySubtract = Lists.newLinkedList();
        List<JSONObject> depositAdd = Lists.newLinkedList();
        List<JSONObject> depositSubtract = Lists.newLinkedList();
        money.put("add", moneyAdd);
        money.put("substract", moneySubtract);
        deposit.put("add", depositAdd);
        deposit.put("substract", depositSubtract);
        UserRating userRating;
        switch (userRole.getRoleType()) {
            case 1:
                //资金方
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount()).add(userAccount.getDueAmount());
                moneyAdd.add(build("累计充值:", userAccount.getMoneyTotalTopup()));
                moneyAdd.add(build("累计实收本息:", userAccount.getPayedAmount()));
                moneySubtract.add(build("累计提现:", userAccount.getMoneyTotalWithdraw()));
                moneySubtract.add(build("累计投资:", userAccount.getIvtFncTotalAmount()));
                othersList.add(build("待收本息:", userAccount.getDueAmount()));
                break;
            case 2:
                //保险公司
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount());
                moneyAdd.add(build("累计充值:", userAccount.getMoneyTotalTopup()));
                moneyAdd.add(build("累计保费收入:", userAccount.getPremiumTotalAmount()));
                moneySubtract.add(build("累计提现:", userAccount.getMoneyTotalWithdraw()));
                break;
            case 3:
                //供应商
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount());
                moneyAdd.add(build("累计充值:", userAccount.getMoneyTotalTopup()));
                moneyAdd.add(build("累计销售:", userAccount.getSaleTotalAmount()));
                moneySubtract.add(build("累计提现:", userAccount.getMoneyTotalWithdraw()));
                break;
            case 4:
                //租赁商
                userRating = userRatingService.getById(userAccount.getId());
                if (userRating != null) {
                    extraMap.put("level", userRating.getLevel());
                } else {
                    extraMap.put("level", "");
                }
                extraMap.put("usableLimitName", build(userAccount.getUsableLimit()));
                extraMap.put("totalLimitName", build(userAccount.getTotalLimit()));
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount());
                moneyAdd.add(build("累计充值:", userAccount.getMoneyTotalTopup()));
                moneyAdd.add(build("累计融资:", userAccount.getIvtFncTotalAmount()));
                moneySubtract.add(build("累计提现:", userAccount.getMoneyTotalWithdraw()));
                moneySubtract.add(build("累计保费支出:", userAccount.getPremiumTotalAmount()));
                moneySubtract.add(build("累计实还本息:", userAccount.getPayedAmount()));
                depositList.add(build("保证金余额:", userAccount.getDepositAmount()));
                depositList.add(build("可用保证金:", userAccount.getDepositUsable()));
                depositList.add(build("冻结保证金:", userAccount.getDepositFrozen()));
                depositList.add(build("在途保证金:", userAccount.getDepositInTransit()));
                depositAdd.add(build("累计充值:", userAccount.getDepositTotalTopup()));
                depositSubtract.add(build("累计提现:", userAccount.getDepositTotalWithdraw()));
                depositSubtract.add(build("累计垫付:", userAccount.getDepositTotalTobepayed()));
                break;
            case 5:
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount());
                //回收商
                break;
            case 6:
                //租赁平台
                userRating = userRatingService.getById(userAccount.getId());
                if (userRating != null) {
                    extraMap.put("level", userRating.getLevel());
                } else {
                    extraMap.put("level", "");
                }
                extraMap.put("usableLimitName", build(userAccount.getUsableLimit()));
                extraMap.put("totalLimitName", build(userAccount.getTotalLimit()));
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount());
                moneyAdd.add(build("累计充值:", userAccount.getMoneyTotalTopup()));
                moneyAdd.add(build("累计融资:", userAccount.getIvtFncTotalAmount()));
                moneySubtract.add(build("累计提现:", userAccount.getMoneyTotalWithdraw()));
                moneySubtract.add(build("累计保费支出:", userAccount.getPremiumTotalAmount()));
                moneySubtract.add(build("累计实还本息:", userAccount.getPayedAmount()));
                depositList.add(build("保证金余额:", userAccount.getDepositAmount()));
                depositList.add(build("可用保证金:", userAccount.getDepositUsable()));
                depositList.add(build("冻结保证金:", userAccount.getDepositFrozen()));
                depositList.add(build("在途保证金:", userAccount.getDepositInTransit()));
                depositAdd.add(build("累计充值:", userAccount.getDepositTotalTopup()));
                depositSubtract.add(build("累计提现:", userAccount.getDepositTotalWithdraw()));
                depositSubtract.add(build("累计垫付:", userAccount.getDepositTotalTobepayed()));
                break;
            default:
                allMoney = allMoney.add(userAccount.getMoneyAmount()).add(userAccount.getDepositAmount());

        }

        return renderOk().put("account", userAccount)
                .put("bank", userBank)
                .put("role", userRole)
                .put("money", money)
                .put("deposit", deposit)
                .put("others", others)
                .put("all", build("资产总额:", allMoney))
                .put("extra", extraMap);
    }

    public JSONObject build(String key, Object value) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", key);

        DecimalFormat df = new DecimalFormat("¥ #,##0.00");
        if (value instanceof BigDecimal) {
            jsonObject.put("value", df.format(value));
        } else {
            jsonObject.put("value", value);
        }

        return jsonObject;
    }

    public String build(BigDecimal value) {
        DecimalFormat df = new DecimalFormat("¥ #,##0.00");
        return df.format(value);

    }

    @PostMapping("bill")
    public ApiResult getBill(AccountBillVo vo) {
        Map m = beanMapper.map(vo, Map.class);
        IPage<FinanceDeal> page = financeDealService.findByCondition(PageKit.buildPage(vo), m);
        DecimalFormat df = new DecimalFormat("¥ #,##0.00");
        List<String> ids = Lists.newArrayList();
        Map<String, UserRole> userRoleMap = Maps.newHashMap();
        page.getRecords().forEach(v -> {
            ids.add(v.getCounterpartyId());
        });
        userRoleMange.getAllUserRoleById(ids, userRoleMap);
        page.convert(v -> {
            Map map = beanMapper.map(v, Map.class);
            map.put("typeName", BillType.getByCode(v.getType()).getName());
            map.put("amountName", df.format(v.getAmount()));
            UserRole payee = userRoleMap.getOrDefault(v.getCounterpartyId(), userRoleConstant);
            UserRole payeeAccess = userRoleConstant;
            if (payee != null) {
                payee.initNme();
                if (StringUtils.isNotBlank(payee.getAccessId())) {
                    payeeAccess = userRoleMap.getOrDefault(payee.getAccessId(), userRoleConstant);
                }
            }
            map.put("payee", StringUtils.isBlank(payee.getMerchantNo()) ? "" : payee.getMerchantNo() + "-"
                    + (StringUtils.isBlank(payee.getMerchantAbbrName()) ? "" : payee.getMerchantAbbrName()));
            map.put("payee1", "");
            if (payee.getRoleType() != null) {
                if (payee != null) {
                    if (payee.getMerchantType().equals(MerchantType.L2.getCode())) {
                        map.put("payee1", MerchantType.getByCode(payee.getMerchantType()).getName()
                                + (StringUtils.isBlank(payeeAccess.getMerchantAbbrName()) ? "" : ("/" + payeeAccess.getMerchantAbbrName())));

                    } else {
                        map.put("payee1", MerchantType.getByCode(payee.getMerchantType()).getName());

                    }
                }
            }
            return map;
        });
        return renderOk().add(page);
    }

    @PostMapping("billType")
    public ApiResult getBill() {
        List list = Lists.newArrayList();
        Arrays.stream(BillType.values()).forEach(v -> {
            if(!v.getCode().equals(0)){
                Map map = Maps.newHashMap();
                map.put("code", v.getCode());
                map.put("name", v.getName());
                list.add(map);
            }
        });
        return renderOk().add(list);
    }

}